<?php


namespace app\common\service;

use app\common\RootException;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Signer\Hmac\Sha256;

class JwtService
{
    /**
     * @var Configuration
     */
    protected $jwtConfig;

    /**
     * @var string jwt加密Key
     */
    protected $jwtKey = '6ab2646c08d99c1ac3b2f691576f9ed0';

    /**
     * 初始化
     * JwtService constructor.
     */
    public function __construct()
    {
        $this->jwtConfig = Configuration::forSymmetricSigner(new Sha256(), InMemory::base64Encoded($this->jwtKey));
    }

    /**
     * 管理后台签发Token
     * @param int $userId 用户ID
     * @param int $minute 过期时间（分钟）
     * @return \Lcobucci\JWT\Token\Plain
     */
    public function issueAdminToken(int $userId)
    {
        $tokenExpire = env('app.admin_token_expire', 240) * 60;
        return $this->generateToken('admin' . $userId, $tokenExpire);
    }

    /**
     * APP客户端签发Token
     * @param int $userId
     * @return string
     */
    public function issueApiToken(int $userId)
    {
        $tokenExpire = env('app.app_token_expire', 240) * 3600;
        return $this->generateToken('task' . $userId, $tokenExpire);
    }

    /**
     * 生成Token
     * @param string $userKey
     * @param int $minute
     * @return string
     */
    protected function generateToken(string $userKey, int $minute)
    {
        $now = new \DateTimeImmutable();
        // 生成JwtToken
        $jwtToken = $this->jwtConfig->builder()->issuedBy('eluchangxing.com')->identifiedBy($this->jwtKey)
            ->issuedAt($now)->expiresAt($now->modify("{$minute} minute"))
            ->withClaim('data', ['userId' => $userKey, 'minute' => $minute])
            ->getToken($this->jwtConfig->signer(), $this->jwtConfig->signingKey())->toString();
        // 通过缓存置换Token
        $accessToken = md5($jwtToken);
        cache($accessToken, $jwtToken, $minute * 60);
        return $accessToken;
    }

    /**
     * Token解析
     * @param string $jwtToken
     * @return \Lcobucci\JWT\Token\DataSet
     */
    public function parseToken(string $jwtToken)
    {
        $token = $this->jwtConfig->parser()->parse($jwtToken);
        return $token->claims();
    }

    /**
     * Token校验
     * @param string $jwtToken
     * @return bool
     */
    public function verifyToken(string $jwtToken)
    {
        $token = $this->jwtConfig->parser()->parse($jwtToken);
        return $this->jwtConfig->validator($token, $this->jwtConfig->validationConstraints()) ? true : false;
    }
}